package com.namecard.namecardapi.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.namecard.namecardapi.entity.*;
import com.namecard.namecardapi.entity.DTO.CardShopDTO;
import com.namecard.namecardapi.entity.vo.*;
import com.namecard.namecardapi.exception.BusinessException;
import com.namecard.namecardapi.mapper.*;
import com.namecard.namecardapi.service.CardInfoService;
import com.namecard.namecardapi.util.Constants;
import com.namecard.namecardapi.util.RedisUtil;
import com.namecard.namecardapi.util.TagUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wzx
 * @since 2023-07-03
 */
@Service
public class CardInfoServiceImpl extends ServiceImpl<CardInfoMapper, CardInfo> implements CardInfoService {

    @Resource
    private CardInfoMapper cardInfoMapper;
    @Resource
    private CardOrderInfoMapper cardOrderInfoMapper;
    @Resource
    private TagInfoMapper tagInfoMapper;
    @Resource
    private OrderInfoMapper orderInfoMapper;
    @Resource
    private UserInfoMapper userInfoMapper;
    @Resource
    private ImageMapper imageMapper;
    @Autowired
    CustomTagMapper customTagMapper;
    @Autowired
    private OrderCardMapper orderCardMapper;
    @Resource
    TagUtil tagUtil;
    @Resource
    private RedisUtil redisUtil;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    private static final String REDIS_PUSH_DATA_1 = "baseBucket_1";
    private static final String REDIS_PUSH_DATA_2 = "baseBucket_2";
    private static final String REDIS_PUSH_DATA_3 = "baseBucket_3";

    @Override
    public BasicCardVO getBasicCard(String cardId) {
        // 通过cardId查询数据
        CardInfo cardInfo = cardInfoMapper.selectOne(new QueryWrapper<CardInfo>()
                .eq("card_id", cardId).select("name", "age", "occupation", "company"));
        // 属性转移
        return new BasicCardVO(cardInfo.getName(), cardInfo.getAge(), cardInfo.getOccupation(), cardInfo.getCompany());
    }

    @Override
    public CardInfoVO getCardAll(String cardId) {
        // 通过cardId查询数据
        CardInfo cardInfo = cardInfoMapper.selectCard(cardId);
        // 解析标签id集合获取标签数据
        if (cardInfo.getTagList() == null) {
            // 标签可为空还有啥好说的，直接返回
            return new CardInfoVO(cardInfo, null);
        }
        JSONArray objects = JSON.parseArray(cardInfo.getTagList());
        // 封装的标签集合
        List<TagVO> tagInfos = new ArrayList<>();
        // 以stream的并行流对list进行遍历操作
        objects.stream()
                .parallel()
                .filter(Objects::nonNull)
                .map(o -> tagInfoMapper.getTagContent(Long.valueOf(String.valueOf(o))))
                .forEach(tagInfos::add);
        return new CardInfoVO(cardInfo, tagInfos);
    }

    @Override
    public void cardInfo(CardInfo cardInfo, String userId) {
        // 完善数据
        try {
            cardInfoMapper.update(cardInfo, new QueryWrapper<CardInfo>().eq("user_id", userId));
        } catch (Exception e) {
            throw new BusinessException(e);
        }
    }
    @Override
    public void updateCard(CardInfo cardInfo, String userId) {
        cardInfoMapper.update(cardInfo, new QueryWrapper<CardInfo>().eq("user_id"
                , userId));
    }

    @Override
    public List<CardInfoVO> showBuyCard(String userId) {
        // 通过userid获取
        CardOrderInfo cardOrderInfo = cardOrderInfoMapper.selectOne(new QueryWrapper<CardOrderInfo>().eq("user_id", userId));
        if (cardOrderInfo==null){return null;}
        String cardList = cardOrderInfo.getCardList();
        JSONArray objects = JSON.parseArray(cardList);
        // 获取已经购买的名片的id列表
        List<String> cardIdList = JSONObject.parseArray(objects.toJSONString(), String.class);
        // 当前时间
        Date currentTime=new Date();
        // 要移除的名片集合
        List<String> cardIdsToRemove = new ArrayList<>();
        // 根据购买名片的id列表获取名片数据
        List<CardInfoVO> result = cardIdList.stream()
                .parallel()
                .map(cardId -> {

                    OrderInfo orderInfo = orderInfoMapper.selectOne(new QueryWrapper<OrderInfo>()
                            .eq("user_id", userId)
                            .eq("shop_id", cardId));
                    if (checkInvalid(currentTime, orderInfo.getInvalidTime())) {
                        return getCardAll(cardId);
                    } else {
                        cardIdsToRemove.add(cardId);
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        if (cardIdList.removeAll(cardIdsToRemove)){
            cardOrderInfoMapper.update(null,new UpdateWrapper<CardOrderInfo>()
                    .eq("user_id",userId)
                    .set("card_list", JSON.toJSONString(cardIdList)));
        }
        return result;
    }

    @Override
    public void timingPush() {
        List<String> listFromRedis1 = redisUtil.getListFromRedis(REDIS_PUSH_DATA_1);
        List<String> listFromRedis2 = redisUtil.getListFromRedis(REDIS_PUSH_DATA_2);
        List<String> listFromRedis3 = redisUtil.getListFromRedis(REDIS_PUSH_DATA_3);
        // 获取redis的缓存redisCardList
        List<String> redisCardList;
        // 获取user_info表所有用户user_id
        List<String> userIdList = userInfoMapper.selectUserIdList();
        // 遍历每个user_id
            for(String userId : userIdList){
                // 一级缓存card_id
                redisCardList=listFromRedis1;
                // 获取每个user_id对应的已购买card_id集合
                CardOrderInfo cardOrderInfo= cardOrderInfoMapper.selectOne(new QueryWrapper<CardOrderInfo>()
                        .eq("user_id", userId));
                if (cardOrderInfo == null || cardOrderInfo.getCardList() == null) {
                    redisUtil.saveListToRedis(userId, listFromRedis1.subList(0, 30), Constants.REDIS_USER_DATA_VALID_TIME);
                    continue;
                }
                String cardList = cardOrderInfo.getCardList();
                JSONArray jsonArray = JSON.parseArray(cardList);
                List<String> hashBuyCardIdList = JSONObject.parseArray(jsonArray.toJSONString(), String.class);
                // 过滤用户已购买的card_id集合
                List<String> filteredBuyCardList1 = filteredBuyCardList(redisCardList,hashBuyCardIdList);
                // 返回所有过滤加在一起的总集合
                List<String> filteredAll = new ArrayList<>(filteredBuyCardList1);
                // 判断用户是否有30条推送 否则从listFromRedis2上再取
                if(filteredAll.size() < Constants.USER_GET_PUSH_CARD_SUM){
                    // 二级缓存card_id
                    redisCardList = listFromRedis2;
                    List<String> filteredBuyCardList2 = filteredBuyCardList(redisCardList,hashBuyCardIdList);
                    filteredAll.addAll(filteredBuyCardList2);
                }
                if (filteredAll.size()< Constants.USER_GET_PUSH_CARD_SUM){
                    // 三级缓存card_id
                    redisCardList=listFromRedis3;
                    List<String> filteredBuyCardList3 = filteredBuyCardList(redisCardList,hashBuyCardIdList);
                    filteredAll.addAll(filteredBuyCardList3);
                }
                // 将过滤出来的cardList保存到redis，key为user_id
                // 如果少于30条就直接推送
                if (filteredAll.size() <= 30){
                    redisUtil.saveListToRedis(userId,filteredAll, Constants.REDIS_USER_DATA_VALID_TIME);
                }else {
                    redisUtil.saveListToRedis(userId,filteredAll.subList(0,30), Constants.REDIS_USER_DATA_VALID_TIME);
                }
            }

    }
    public List<String> filteredBuyCardList(List<String> redisCardList,List<String> hashBuyCardIdList){

        return redisCardList.stream()
                .parallel()
                .filter(cardId -> !hashBuyCardIdList.contains(cardId))
                .collect(Collectors.toList());
    }

    @Override
    public List<CardAllInfoVO> userGetPush(String userId) {
        // 从redis获取userId对应的cardIdList
        List<String> cardIdList = redisUtil.getListFromRedis(userId);
        return getResultList(cardIdList);
    }

    /**
     检查是否过期 true 未过期 false 已过期
     */
    public boolean checkInvalid(Date currentTime,Date invalidTime){
        return    currentTime.compareTo(invalidTime) < 0;
    }


    /**
     * 名片市场
     * @return 结果数据
     */
    @Override
    public PageDataVO cardShop(CardShopDTO cardShopDTO) {

        String title = cardShopDTO.getTitle();
        // 获取所有名片的id
        List<String> cardIdList = cardInfoMapper.selectCardIdList((cardShopDTO.getPage()-1)* cardShopDTO.getLimit(),cardShopDTO.getLimit(), title);
        for (CustomTagInfo customTagInfo : customTagMapper.selectList(new QueryWrapper<CustomTagInfo>()
                .eq("title", title))) {
            CardInfo cardInfo = cardInfoMapper.selectOne(new QueryWrapper<CardInfo>()
                    .eq("user_id", customTagInfo.getUserId()));
            cardIdList.add(cardInfo.getCardId());
        }
        Integer cardIdListCount = cardInfoMapper.cardIdListCount(title);
        Long title1 = customTagMapper.selectCount(new QueryWrapper<CustomTagInfo>()
                .eq("title", title));
        List<CardAllInfoVO> resultList = getResultList(cardIdList);
        for (CardAllInfoVO cardAllInfoVO : resultList) {
            List<CustomTagInfo> customTagInfoList = customTagMapper.selectList(new QueryWrapper<CustomTagInfo>()
                    .eq("user_id", cardAllInfoVO.getCardInfo().getUserId()));
            List<String> customTags = customTagInfoList
                    .stream()
                    .map(CustomTagInfo::getTitle)
                    .collect(Collectors.toList());
            cardAllInfoVO.setCustomTags(customTags);
        }
        return new PageDataVO((int) (title1+ cardIdListCount),resultList);
    }


    private List<CardAllInfoVO> getResultList(List<String> cardIdList){
        // 从mysql查询获取所有card返回list集合，获取所有名片对应的标签数据
        List<CardAllInfoVO> resultList = cardIdList.stream()
                .parallel()
                .map(cardId -> {
                    CardInfo cardInfo = cardInfoMapper.selectCardInfo(cardId);
                    //根据userId查userInfo信息查到Colour
                    UserInfo userInfo = userInfoMapper.selectOne(new QueryWrapper<UserInfo>()
                            .eq("user_id", cardInfo.getUserId()));
                    if(userInfo != null){
                        cardInfo.setColour(userInfo.getColour());
                    }else {
                        cardInfo.setColour(null);
                    }
                    // 从每一个订单数据中获取标签id从而得到标签集合数据
                    String tagList = cardInfo.getTagList();
                    if (tagList == null || "\"\"".equals(tagList)) {
                        // 标签可为空还有啥好说的，直接返回
                        return new CardAllInfoVO(cardInfo, null);
                    }
                    List<TagVO> tagInfos = tagUtil.getTagList(tagList);
                    if (cardInfo.getUserImage() != null) {
                        cardInfo.setUserImage(imageMapper.selectPath(cardInfo.getUserImage()));
                    }
                    return new CardAllInfoVO(cardInfo, tagInfos);
                })
                .collect(Collectors.toList());
        return resultList;
    }

    /**
     * 特殊数据购买符合的数据条数查询
     */
    @Override
    public int specialDataList(SpecialShopVO specialShopVO, String userId) {
        List<CardInfo> list = cardInfoMapper.selectSpecialDataListAllTrue(specialShopVO);
        if (list == null || list.size() == 0){return 0;}
        // 将结果的数据存入redis中,有效期为10min
        redisUtil.saveJsonStringToRedis(userId + Constants.SPECIAL_PAY_SUFFIX, list, Constants.SPECIAL_PAY_VALID_TIME);
        return list.size();
    }

    /**
     * 获取每日免费卡片
     * @return
     */
    @Override
    public DailyRandomCard getFreeCard(String userId) {
        // 从redis中获取数据
        String data = stringRedisTemplate.opsForValue().get("userCards:" + userId);

        DailyRandomCard dailyRandomCard = JSON.parseObject(data, DailyRandomCard.class);
        
        String date = dailyRandomCard.getDate();

        String randomCardAllInfoToJson = dailyRandomCard.getRandomCardAllInfoToJson();
        List<CardAllInfoVO> cardAllInfoVOS = JSON.parseObject(randomCardAllInfoToJson, new TypeReference<List<CardAllInfoVO>>() {});
        //清除已为好友的卡片
        CardOrderInfo cardOrderInfo = cardOrderInfoMapper.selectOne(new QueryWrapper<CardOrderInfo>()
                .eq("user_id", userId));

        if (cardOrderInfo!= null) {
            String cardList = cardOrderInfo.getCardList();
            JSONArray jsonArray = JSON.parseArray(cardList);
            List<String> cardIdList = JSONObject.parseArray(jsonArray.toJSONString(), String.class);
            for (int i = 0 ;i <  cardAllInfoVOS.size(); i++) {
                for (String userid : cardIdList) {
                    if (cardAllInfoVOS.get(i).getCardInfo().getCardId().equals(userid)){
                        cardAllInfoVOS.remove(i);break;
                    }
                }
            }
        }

        DailyRandomCard dailyRandomCard2 = new DailyRandomCard();
        dailyRandomCard2 .setDate(date);
        dailyRandomCard2.setRandomCardAllInfoToJson(JSON.toJSONString(cardAllInfoVOS));
        return dailyRandomCard2;
    }

    /**
     * 获取曝光度前20的卡片
     * @return
     */
    @Override
    public List<CardAllInfoVO> getTop20(String titleId) {
        List<CardAllInfoVO> cardAllInfoVOS = new ArrayList<>();
        List<CardInfo> cardInfos = cardInfoMapper.selectTop20(titleId);
        for (CardInfo cardInfo : cardInfos) {
            String path = imageMapper.selectPath(cardInfo.getUserImage());
            if (path != null) {
                cardInfo.setUserImage(path);
            }
            CardAllInfoVO cardAllInfoVO = new CardAllInfoVO();
            cardAllInfoVO.setCardInfo(cardInfo);
            List<TagVO> tagVOList = tagUtil.getTagList(cardInfo.getTagList());
            cardAllInfoVO.setTagVOList(tagVOList);
            List<String> customTags = customTagMapper.selectList(new QueryWrapper<CustomTagInfo>()
                            .eq("user_id", cardInfo.getUserId()))
                    .stream()
                    .map(CustomTagInfo::getTitle)
                    .collect(Collectors.toList());
            cardAllInfoVO.setCustomTags(customTags);
            cardAllInfoVOS.add(cardAllInfoVO);
        }
        return cardAllInfoVOS;
    }

    /**
     * 获取好友列表
     * @param userId
     * @return
     */
    @Override
    public List<FriendsVO> getFriends(String userId) {
        // 通过userid获取
        CardOrderInfo cardOrderInfo = cardOrderInfoMapper.selectOne(new QueryWrapper<CardOrderInfo>()
                .eq("user_id", userId));
        if (cardOrderInfo == null){return null;}
        String cardList = cardOrderInfo.getCardList();
        JSONArray objects = JSON.parseArray(cardList);
        // 获取已经购买的名片的id列表
        List<String> userIdList = JSONObject.parseArray(objects.toJSONString(), String.class);
        Set<String> userIdSet = new HashSet<>(userIdList);
        List<CardInfo> cardInfoList = userIdSet.stream().map(id -> {
            CardInfo cardInfo = cardInfoMapper.selectOne(new QueryWrapper<CardInfo>()
                    .eq("user_id", id));
            if (cardInfo == null){return null;}
            return cardInfo;
        }).collect(Collectors.toList());
        return cardInfoList.stream().parallel().map(cardInfo -> {
            if (cardInfo == null){return null;}
            UserInfo userInfo = userInfoMapper.selectOne(new QueryWrapper<UserInfo>()
                    .eq("user_id", cardInfo.getUserId()));
            if (userInfo.getUserImage() != null) {
                cardInfo.setUserImage("/img/avatar/" + userInfo.getUserImage() + ".jpg");
            }
            if (userInfo.getColour()!= null) {
                cardInfo.setColour(userInfo.getColour());
            }
            return new FriendsVO(cardInfo, null);
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }

    /**
     * 判断是否有重复的用户id
     * @return
     */
    @Override
    public Boolean duplicateUserId() {
        List<CardInfo> duplicateUsers = list(new QueryWrapper<CardInfo>()
                .select("user_id")
                .groupBy("user_id")
                .having("count(user_id) > 1"));
        return !duplicateUsers.isEmpty();
    }
}
